package com.wechat.service.storage;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.swak.annotation.FluxService;
import com.swak.entity.YesNo;
import com.swak.persistence.OrderBy;
import com.swak.persistence.QueryCondition;
import com.swak.service.BaseService;
import com.swak.utils.Lists;
import com.swak.utils.StringUtils;
import com.swak.utils.time.DateTimes;
import com.wechat.dto.ChatAddContactsDTO;
import com.wechat.dto.ChatDTO;
import com.wechat.dto.ChatRoomDTO;
import com.wechat.dto.ContactDTO;
import com.wechat.entity.Chat;
import com.wechat.enums.ContactType;
import com.wechat.enums.MessageType;
import com.wechat.login.Login;
import com.wechat.login.LoginService;
import com.wechat.service.ChatRoomService;
import com.wechat.service.ChatService;
import com.wechat.service.ContactService;
import com.wechat.service.MessageService;
import com.wechat.service.storage.mapper.ChatMapper;

/**
 * 描述
 * 
 * @author Auto Generator
 * @date 2022-10-21T23:59:27.243629400
 */
@FluxService
@Service("wechatChatService")
public class ChatServiceImpl extends BaseService<Chat, String> implements ChatService {

	@Autowired
	private ChatMapper chatMapper;
	@Autowired
	private MessageService messageService;
	@Autowired
	private ChatRoomService roomService;
	@Autowired
	private ContactService contactService;

	@Override
	public ChatDTO get(String id) {
		return ChatDTO.convert(this.chatMapper.get(id));
	}

	@Override
	@Transactional
	public ChatDTO lock(String id) {
		return ChatDTO.convert(this.chatMapper.lock(id));
	}

	@Override
	@Transactional
	public ChatDTO create(ChatAddContactsDTO addContacts) {
		ChatDTO chat = addContacts.getChat() != null && StringUtils.isNotBlank(addContacts.getChat().getId())
				? this.get(addContacts.getChat().getId())
				: null;

		// 创建一个新的聊天室
		if (chat == null || chat.getType() != ContactType.Chat_Room.getType()) {

			// 创建聊天人的容器
			List<ContactDTO> newContacts = Lists.newArrayList(addContacts.getContacts());

			// 添加当前聊天
			newContacts.add(ContactDTO.of().setId(chat.getId()).setNickName(chat.getNickName()));

			// 添加当前的用户
			Login login = LoginService.login();
			newContacts.add(ContactDTO.of().setId(login.getId()).setNickName(login.getNickName()));

			ChatRoomDTO room = this.roomService.create(newContacts);
			return this.create(ChatDTO.of().setId(room.getId()).setNickName(room.getNickName())
					.setType(ContactType.Chat_Room.getType()).setContactCount(room.getUserCount()));
		}

		// 存在的聊天室添加联系人
		ChatRoomDTO room = this.roomService.addContacts(ChatRoomDTO.of().setId(chat.getId()),
				addContacts.getContacts());

		// 返回聊天窗口
		return this.create(ChatDTO.of().setId(room.getId()).setNickName(room.getNickName())
				.setType(ContactType.Chat_Room.getType()));
	}

	@Override
	@Transactional
	public ChatDTO create(ContactDTO contact) {
		return this.create(
				ChatDTO.of().setId(contact.getId()).setType(contact.getType()).setNickName(contact.getNickName()));
	}

	@Override
	@Transactional
	public ChatDTO create(ChatDTO chat) {

		// 执行新增
		this.doCreate(chat);

		// 返回最新数据
		return this.get(chat.getId());
	}

	private boolean doCreate(ChatDTO chat) {
		int add = Chat.of().setId(chat.getId()) // 主键
				.setType(chat.getType()) // 联系人类型
				.setNickName(chat.getNickName()) // 名称
				.setContactCount(1) // 联系人的数量
				.setChatOrder(0) // 排序
				.setUnReadCount(0)// 未读信息数量
				.setLastMsgContent("你们已经是好友，可以开始聊天了") // 信息
				.setLastMsgType(MessageType.Txt.getV())// 信息
				.setLastMsgDate(DateTimes.now())// 信息
				.setMsgSequence(chat.getMsgSequence() == null ? 0L : chat.getMsgSequence())// 信息序号
				.setOthersAtMe(YesNo.No.getType())// 是否有其他人@me
				.setIsAlert(YesNo.Yes.getType())// 是否提醒，默认是true
				.setIsTop(YesNo.No.getType())// 是否置顶
				.setIsDel(YesNo.No.getType()) // 是否删除
				.setIsHide(YesNo.No.getType()) // 是否隐藏
				.setIsFriend(YesNo.No.getType()) // 是否好友
				.insertive(true)// 保存
				.updateOrInsertResult();// 保存结果

		// 这个时候需要初始化
		if (add == 1) {
			this.contactService.create(
					ContactDTO.of().setId(chat.getId()).setNickName(chat.getNickName()).setType(chat.getType()));
		}

		// 返回是否插入数据成功
		return add == 1;
	}

	/**
	 * 第一次接受数据:
	 * 创建聊天,并初始化
	 * 
	 * 否则：
	 * 设置为未删除，且添加序列号;
	 */
	@Override
	@Transactional
	public Long receiveMessage(ChatDTO chat) {
		int update = Chat.of().setMsgSequence(1L).setIsDel(YesNo.No.getType()).setId(chat.getId()).merge(false)
				.updateOrInsertResult();
		// 没有对应的数据，第一收到消息，很有可能没有数据
		if (!(update == 1)) {
			Boolean add = this.doCreate(chat.setMsgSequence(1L));
			// 如果插入数据失败，则更新数据
			if (!add) {
				Chat.of().setMsgSequence(1L).setIsDel(YesNo.No.getType()).setId(chat.getId()).merge(false)
						.updateOrInsertResult();
			}
		}
		return Chat.of().setId(chat.getId()).get().getMsgSequence();
	}

	@Override
	@Transactional
	public ChatDTO updateMessage(ChatDTO chat) {
		Chat entity = chat.transform().setIsDel(YesNo.No.getType());
		this.chatMapper.updateSelective(entity);
		return this.get(chat.getId());
	}

	@Override
	@Transactional
	public ChatDTO updateFlag(ChatDTO chat) {
		Chat entity = chat.transform().setIsDel(YesNo.No.getType());
		this.chatMapper.updateSelective(entity);

		// 修改是否好友时，需要同步刷新到联系人中
		if (entity.getIsFriend() != null) {
			this.contactService.syncIsFriend(ContactDTO.of().setId(entity.getId()).setIsFriend(entity.getIsFriend()));
		}
		return this.get(chat.getId());
	}

	@Override
	@Transactional
	public void delete(ChatDTO chat) {
		Chat deleted = Chat.of().setId(chat.getId()).get();
		deleted.setLastMsgContent(null).setLastMsgType(null).setLastMsgDate(null).setIsDel(YesNo.Yes.getType())
				.update();
		this.messageService.deleteByChat(deleted.getId());
	}

	@Override
	public List<ChatDTO> list() {
		QueryCondition qc = new QueryCondition();
		qc.getCriteria().andEqualTo(Chat.DelFlag, Boolean.FALSE);
		qc.getCriteria().andEqualTo(Chat.IsDel, YesNo.No.getType());
		qc.setOrderByClause(OrderBy.of().Desc(Chat.IsTop).Desc(Chat.LastMsgDate).Desc(Chat.ChatOrder));
		return ChatDTO.convert(this.chatMapper.queryByCondition(qc));
	}

	@Override
	public Integer unreads() {
		return this.chatMapper.unreads();
	}

	// ******************* 同步数据，不要级联更新其他数据 ******************

	@Transactional
	public void syncNickName(ChatDTO chat) {
		Chat.of().setNickName(chat.getNickName()).setId(chat.getId()).updateSelective();
	}

	@Transactional
	public void syncIsFriend(ChatDTO chat) {
		Chat.of().setIsFriend(chat.getIsFriend()).setId(chat.getId()).updateSelective();
	}
}
